package cn.cai.pethome.shop.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.cai.pethome.baidu.dto.AuditResultDto;
import cn.cai.pethome.baidu.service.AuthService;
import cn.cai.pethome.base.util.MD5Utils;
import cn.cai.pethome.base.util.MailUtil;
import cn.cai.pethome.emp.domain.Employee;
import cn.cai.pethome.emp.mapper.IEmployeeMapper;
import cn.cai.pethome.logininfo.domain.Logininfo;
import cn.cai.pethome.logininfo.mapper.LogininfoMapper;
import cn.cai.pethome.shop.domain.ExamineRecord;
import cn.cai.pethome.shop.domain.Shop;
import cn.cai.pethome.shop.dto.ShopDto;
import cn.cai.pethome.shop.mapper.ExamineRecordMapper;
import cn.cai.pethome.shop.mapper.ShopMapper;
import cn.cai.pethome.shop.service.IExamineRecordService;
import cn.cai.pethome.shop.service.IShopService;
import cn.cai.pethome.base.service.impl.BaseServiceImpl;
import com.alibaba.fastjson2.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.crypto.ExemptionMechanism;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xiaocai
 * @since 2022-08-27
 */
@Service
public class ShopServiceImpl<EmployeeMapper> extends BaseServiceImpl<Shop> implements IShopService {



    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private ShopMapper shopMapper;
    @Autowired
    private IEmployeeMapper employeeMapper;

    @Autowired
    private ExamineRecordMapper examineRecordMapper;

    @Value("${baidu.ai.ak}")
    private String ak;

    @Value("${baidu.ai.sk}")
    private String sk;

    @Autowired
    private MailUtil mailUtil;

    /**
     * 商家入驻
     * @param shop 商家入驻对象
     */
    @Transactional
    @Override
    public void settlement(Shop shop) {
        //1.校验参数 自己完成
        Assert.isTrue(StringUtils.hasText(shop.getName()), "店铺名称不能为空！");
        Assert.isTrue(shop.getAdmin().getPassword().equals(shop.getAdmin().getComfirmPassword()), "两次密码不一致！");

        //2.保存t_loginInfo 登录账号信息 返回主键
        Logininfo logininfo = new Logininfo();
        logininfo.setUsername(shop.getAdmin().getUsername());
        logininfo.setPhone(shop.getAdmin().getPhone());
        logininfo.setEmail(shop.getAdmin().getEmail());
        //盐值：MD5加密的时候洒了一把盐，目的是增加密码的安全性
        //UUID：生成绝对唯一的字符串
        String salt = UUID.randomUUID().toString();
        logininfo.setSalt(salt);
        //MD5加密，
        String md5password = MD5Utils.encrypByMd5(shop.getAdmin().getPassword() + salt);
        logininfo.setPassword(md5password);

        logininfoMapper.add(logininfo);

        //3.保存店铺信息 t_shop       返回主键
        shopMapper.add(shop);


        //4.保存店铺管理员信息 t_employee 返回主键
        Employee admin = shop.getAdmin();
        admin.setSalt(salt);
        admin.setPassword(md5password);
        admin.setShop_id(shop.getId());
        admin.setLogininfo_id(logininfo.getId());
        employeeMapper.add(admin);

        //5.修改店铺信息的admin_id外键列的值
        shop.setAdminId(admin.getId());
        shopMapper.update(shop);



    }

    /**
     * 平台员工：审核商家入驻信息
     * jackson转换的
     * @RequestBody: 读取请求体里面的json字符串，转化为形参变量类型指定的实体类对象
     * @ResponseBody: 将你controller方法返回的对象转化为json字符串，放入响应的消息体里面返回给前端
     * @param         //shopDt  前端的对象
     * @return
     */
    @Transactional
    @Override
    public void audit(ShopDto shopDto) {

        Shop shop = shopMapper.findById(shopDto.getShopId());//先根据带回来的t_shop的id查询出来，对象
        Employee admin = employeeMapper.findById(shopDto.getAdminId());//先根据带回来的t_Employee的id查询出来，对象

         //1.获取百度AI的access_token
        String access_token = AuthService.getAuth(ak, sk);

        //2.携带token访问文本审核接口 java发送http请求
        String auditResultJsonStr = AuthService.auditText(access_token, shop.getName());

            //3.将审核结果的json字符串转化为实体类对象
        //JSON工具包：jsonlib,SpringMVC官方的jackson，阿里巴巴的fastjson，谷歌的gson，糊涂工具包的JSONUtil
        AuditResultDto auditResultDto = JSON.parseObject(auditResultJsonStr, AuditResultDto.class);//阿里巴巴的fastjson

        //判断 错误码是否为空和错误提示是否存在
        if(auditResultDto.getError_code() == null
                && !StringUtils.hasText(auditResultDto.getError_msg())){
              //如果合格ConclusionType返回的是1
           if(auditResultDto.getConclusionType() == 1){
               //1.修改状态：t_shop,t_employee
               //做法有多种，1)先通过id查询一个shop对象来修改
               //          2）直接在mapperxml中写一个只修改状态的sql语句,new shop 和new employee
               //先修改t_shop表
               /* Shop shop = shopMapper.findById(shopDto.getShopId());//先根据带回来打t_shop的id查询出来，对象*/
               shop.setState(shopDto.getAuditResult());//查询出来的shop对象，在给他重新状态赋值
               shopMapper.update(shop);//在修改

               //4.再修改t_employee表

               admin.setState(shopDto.getAuditResult());
               employeeMapper.update(admin);

               //5..添加一条审核记录 这里我们要用自己创建一个新表专门存取驳回或者拒绝理由表t_examine_record
               ExamineRecord examineRecord = new ExamineRecord();
               examineRecord.setShopId(shopDto.getShopId());
               examineRecord.setExamineResult(shopDto.getAuditResult());
               examineRecord.setContent(shopDto.getReason());
               //审核人id姓名：需要做了登录功能后，获取当前登录用户信息得来，这里暂时先写死

               examineRecord.setExamineId(307L);
               examineRecord.setExamineName("yhptest");

               examineRecordMapper.add(examineRecord);
            }
        }

        /**
         * 6.发送邮件
         * 由于发送邮件这个操作本身比较耗时，推荐使用异步编程方案
         *    1)新开一个分支线程去执行发送邮件
         *    2)线程池
         */
    new Thread(new Runnable() {
        @Override
        public void run() {
            String text = null;
            if (shopDto.getAuditResult() == 1){
                text = "<h1>恭喜您 ，审核通过了！</h1>" +
                        "<br/>" +
                        "<span>您可以点击以下链接进行激活：</span>" +
                        "<br/>" +
                        "<a href='http://localhost:8080/shop/activate/"+shopDto.getShopId()+"'>入驻激活</a>";

            }else {
                text = "<h1>恭喜您 ，审核通过了！</h1>" +
                        "<br/>" +
                        "<span>原因是："+shopDto.getReason()+"</span>";
            }
            mailUtil.sendEmail("【宠物之家】商家入驻审核结果通知！！！",text,admin.getEmail(),null);
        }
    }).start();



    }

    /**
     * 激活
     * @param id 激活id
     */
    @Transactional
    @Override
    public void updateStated(Long id) {
        //更改shop的State
        shopMapper.updateStated(id);
        //更改emp的State
        Long admin_id = shopMapper.findById(id).getAdmin_id();
        employeeMapper.updateStated(admin_id);
    }

    /**
     * 批量导入后缀名为： xls(03)  xlsx(07) 的数据
     * @param file
     */
    @Transactional
    @Override
    public void importExecl(MultipartFile file) {
        try {
            ImportParams params = new ImportParams();
            /**
             * 导入ExcelImportUtil   导出ExcelExportUtil
             * 实体类里面需要导入或者导出的字段上面需要添加@Excel注解
             *  并指定name属性，必须和excel文件的表头名称保持一致
             * 如果实体类里面有关联对象，关联对象的成员变量上面添加@ExcelEntity注解，关联实体类里面的字段上面照常写@Excel注解
             * 如果是导入：上传的MultipartFile文件对象，直接获取getInputStream()
             * 如果是导出：需要输出流，直接从HttpServletResponse对象getOutputStream()
             */
            List<Shop> shops = ExcelImportUtil.<Shop>importExcel(file.getInputStream(), Shop.class, params);
            //这里已经得到List<Shop> 就可以写for循环了：插入3张表的数据
            for (Shop shop : shops) {
                //每一行都来一次商家入驻表单提交
                this.settlement(shop);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }

    }


}
